package services

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"time"

	"yuanaiproblem/dao"
	models "yuanaiproblem/dao/model"
	"yuanaiproblem/migrations/redis"
	"yuanaiproblem/models/dto"
	"yuanaiproblem/utils"

	goredis "github.com/go-redis/redis/v8"
	"gorm.io/gorm"
)

// SaveQuestions 将编辑后的临时题目（Redis缓存）存入数据库，删除临时缓存
// 参数：user: 当前用户（权限校验tempID: 临时题目的Redis键后缀
// 返回：questions: 编辑后的题目列表

func SaveQuestions(user models.User, tempID string, questions []models.Question) error {
	ctx := context.Background()
	cacheKey := "temp_questions:" + tempID

	// 从Redis获取临时题目缓存
	cacheJSON, err := redis.RedisClient.Get(ctx, cacheKey).Result()
	if err != nil {
		if err == goredis.Nil {
			return errors.New("临时题目不存在或已过期")
		}
		return fmt.Errorf("查询缓存失败: %w", err)
	}

	// 解析缓存数据
	var cacheData struct {
		UserID    int32             `json:"user_id"`
		Questions []models.Question `json:"questions"`
		CreatedAt time.Time         `json:"created_at"`
	}
	if err := json.Unmarshal([]byte(cacheJSON), &cacheData); err != nil {
		return fmt.Errorf("解析缓存数据失败: %w", err)
	}

	// 权限校验
	if cacheData.UserID != user.ID {
		return errors.New("无权限操作此临时题目")
	}

	// 批量保存题目到数据库
	for i, q := range questions {
		// 从缓存中获取原始题目
		var cacheQuestion models.Question
		if i < len(cacheData.Questions) {
			cacheQuestion = cacheData.Questions[i]
		}

		// 合并字段：q的字段为空时，使用cacheQuestion的字段
		questionToSave := models.Question{
			ID:           q.ID, // ID 保持不变
			Title:        utils.Coalesce(q.Title, cacheQuestion.Title),
			QuestionType: utils.Coalesce(q.QuestionType, cacheQuestion.QuestionType),
			Options:      utils.Coalesce(q.Options, cacheQuestion.Options),
			Answer:       utils.Coalesce(q.Answer, cacheQuestion.Answer),
			Explanation:  utils.Coalesce(q.Explanation, cacheQuestion.Explanation),
			Keywords:     utils.Coalesce(q.Keywords, cacheQuestion.Keywords),
			Language:     utils.Coalesce(q.Language, cacheQuestion.Language),
			AiModel:      utils.Coalesce(q.AiModel, cacheQuestion.AiModel),
			UserID:       user.ID,     // 强制使用当前用户ID
			CreatedAt:    q.CreatedAt, // 使用传入的创建时间
			UpdatedAt:    time.Now(),  // 更新时间设为当前时间
		}

		// 保存到数据库
		if err := dao.CreateQuestion(&questionToSave); err != nil {
			return fmt.Errorf("保存题目失败: %w", err)
		}
	}

	// 删除临时缓存
	if err := redis.RedisClient.Del(ctx, cacheKey).Err(); err != nil {
		log.Printf("警告: 删除临时缓存失败: %v", err)
	}

	return nil
}

// DeleteQuestion 软删除题目
// 参数：currentUserID: 当前用户ID isAdmin: 是否为管理员 questionID: 题目ID
// 返回：删除时间、错误（nil表示成功）
func DeleteQuestion(currentUserID int32, isAdmin bool, questionID uint) (time.Time, error) {
	// 查询题目（包含已软删除记录）
	question, err := dao.GetQuestionByIDWithDeleted(questionID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return time.Time{}, errors.New("题目不存在")
		}
		return time.Time{}, err
	}

	// 若已软删除，直接返回删除时间
	if !question.DeletedAt.Time.IsZero() {
		return question.DeletedAt.Time, nil
	}

	// 权限校验：非管理员只能删除自己的题目
	if !isAdmin && question.UserID != currentUserID {
		return time.Time{}, errors.New("无权限删除此题目")
	}

	// 检查题目是否被引用（被引用则禁止删除）
	refCount, err := dao.CountQuestionReferences(questionID)
	if err != nil {
		return time.Time{}, fmt.Errorf("查询引用失败: %w", err)
	}
	if refCount > 0 {
		return time.Time{}, errors.New("题目已被试卷引用，无法删除")
	}

	// 执行软删除
	if err := dao.DeleteQuestion(question); err != nil {
		return time.Time{}, fmt.Errorf("删除失败: %w", err)
	}

	return question.DeletedAt.Time, nil
}

// UpdateQuestion 更新题目信息（支持部分字段更新）
// 参数： currentUserID: 当前用户ID isAdmin: 是否为管理员 questionID: 题目ID title等指针参数: 待更新字段（nil表示不更新）
// 返回：更新后的题目、错误（nil表示成功）
func UpdateQuestion(
	currentUserID int32,
	isAdmin bool,
	questionID uint,
	title, questionType, options, answer, explanation, keywords, language *string,
) (*models.Question, error) {
	// 查询待更新题目
	question, err := dao.GetQuestionByID(questionID)
	if err != nil {
		return nil, err
	}

	// 权限校验：非管理员只能更新自己的题目
	if !isAdmin && question.UserID != currentUserID {
		return nil, errors.New("无权限更新此题目")
	}

	// 构建更新字段（仅非nil参数参与更新）
	updates := make(map[string]interface{})
	if title != nil {
		updates["title"] = *title
	}
	if questionType != nil {
		updates["question_type"] = *questionType
	}
	if options != nil {
		updates["options"] = *options
	}
	if answer != nil {
		updates["answer"] = *answer
	}
	if explanation != nil {
		updates["explanation"] = *explanation
	}
	if keywords != nil {
		updates["keywords"] = *keywords
	}
	if language != nil {
		updates["language"] = *language
	}

	// 执行更新并返回最新数据
	if len(updates) > 0 {
		updates["updated_at"] = time.Now() // 强制更新时间戳
		if err := dao.UpdateQuestion(question, updates); err != nil {
			return nil, err
		}
		return dao.GetQuestionByID(questionID)
	}

	return question, nil // 无更新字段时直接返回原数据
}

// GetUserQuestions 分页获取用户名下的题目
// 参数：userID: 用户IDpage: 页码pageSize: 每页数量
// 返回：查询结果（含总数和列表）、错误（nil表示成功）
func GetUserQuestions(userID int32, page, pageSize int) (*dto.UserQuestionResult, error) {
	// 分页查询用户题目
	questions, total, err := dao.GetUserQuestions(userID, page, pageSize)
	if err != nil {
		return nil, err
	}

	return &dto.UserQuestionResult{
		Count: total,
		List:  questions,
	}, nil
}
